<style>
  .layui-form-item .layui-input-company {width: auto;padding-right: 10px;line-height: 38px;}
</style>
<div class="layuimini-container layuimini-page-anim">
  <div class="layuimini-main">
    <table id="tableId" lay-filter="tableFilter"></table>

    <fieldset class="layui-elem-field">
      <legend>新增/编辑计划任务</legend>
      <div class="layui-field-box">
        <form class="layui-form layuimini-form" lay-filter="form" id="form">
          <input type="hidden" name="config_filename" value="crontab">
          <div class="layui-form-item">
            <label class="layui-form-label required">任务类型</label>
            <div class="layui-input-inline">
              <select name="type" lay-filter="type" lay-verify="required" lay-reqtext="任务类型不能为空" id="type">
                <option value="">请选择任务类型</option>
                <option value="reseed">辅种任务</option>
                <option value="move">转移任务</option>
                <option value="rss">Rss下载任务</option>
                <option value="spiders">免费种爬虫下载任务</option>
                <!-- <option value="url">访问URL</option>
                <option value="shell">Shell脚本</option>
                <option value="patch">备份目录</option>
                <option value="ddns">动态域名DDNS</option>
                <option value="clear">清除日志</option> -->
              </select>
            </div>
          </div>
          <div class="layui-form-item">
            <label class="layui-form-label required">任务名称</label>
            <div class="layui-input-block">
              <input type="text" name="name" lay-verify="required" lay-reqtext="任务名称不能为空" placeholder="请输入任务名称" class="layui-input" id="name">
              <tip>给任务起个名字，方便你找到它。</tip>
            </div>
          </div>
          <div class="layui-form-item">
            <label class="layui-form-label">任务使能</label>
            <div class="layui-input-block">
              <input type="checkbox" name="switch" lay-skin="switch" lay-text="YES|NO" lay-filter="switch" id="switch">
            </div>
          </div>
          <div class="layui-form-item">
            <label class="layui-form-label">通知启动</label>
            <div class="layui-input-block">
              <input type="checkbox" name="notify[enable]" lay-skin="switch" lay-text="YES|NO" lay-filter="switch" id="notify-enable">
            </div>
          </div>
          <div class="layui-form-item">
            <label class="layui-form-label">变化通知</label>
            <div class="layui-input-block">
              <select name="notify[notify_on_change]">
                <option value="off">每次运行都通知</option>
                <option value="on">成功数+失败数大于0时通知</option>
                <option value="only_success">成功数大于0</option>
                <option value="only_fails">失败数大于0</option>
              </select>
            </div>
          </div>
          <div class="layui-form-item">
            <label class="layui-form-label">通知渠道</label>
            <div class="layui-input-block">
              <select name="notify[channel]" id="notify_channels"></select>
            </div>
          </div>
          <div class="layuimini-form" id="crontab_type_view"></div>

          <div class="layui-form-item">
            <div class="layui-input-block">
              <button class="layui-btn layui-btn-normal" lay-submit lay-filter="saveBtn">确认保存</button>
              <button class="layui-btn layui-btn-primary" data-refresh="刷新">刷新</button>
            </div>
          </div>
        </form>
      </div>
    </fieldset>
  </div>
</div>


<!-- 模板：通知渠道 单选框 -->
<script id="notify_option_tpl" type="text/html">
  {{#  layui.each(d, function(index, item){ }}
  <option value="{{ item.name }}">{{ item.name }}</option>
  {{#  }); }}
</script>

<!-- 模板：计划任务配置字段 -->
<script type="text/html" id="crontab_type_tpl">
  <input type="hidden" name="action" value="{{ d.action || 'add'}}">
  {{# if (d.action === 'edit') { }}
  <input type="hidden" name="uuid" value="">
  <input type="hidden" name="startTime" value="">
  {{# } }}

  <div class="layui-form-item">
    <label class="layui-form-label required">执行周期</label>
    <div class="layui-inline">
      <div class="layui-input-inline" style="width: 100px;">
        <select name="where" lay-filter="where" lay-verify="required" lay-reqtext="执行周期不能为空" id="where">
          <option value="day" {{ d.where === 'day' ? 'selected' : ''}}>每天</option>
          <option value="day_n" {{ d.where === 'day_n' ? 'selected' : ''}}>N天</option>
          <option value="hour" {{ d.where === 'hour' ? 'selected' : ''}}>每小时</option>
          <option value="hour_n" {{ d.where === 'hour_n' ? 'selected' : ''}}>N小时</option>
          <option value="minute_n" {{ d.where === 'minute_n' ? 'selected' : ''}}>N分钟</option>
          <option value="week" {{ d.where === 'week' ? 'selected' : ''}}>每星期</option>
          <option value="month" {{ d.where === 'month' ? 'selected' : ''}}>每月</option>
        </select>
      </div>
    </div>
    <span id="crontab_where_view"></span>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label">Crontab表达式</label>
    <div class="layui-input-block">
      <input type="text" name="crontab" lay-reqtext="Crontab表达式" placeholder="请输入Crontab表达式，如果不懂请留空。" class="layui-input" id="crontab">
      <tip>Crontab表达式优先级高于执行周期。如果不懂请留空。</tip>
    </div>
  </div>

  {{# if (d.type === 'reseed') { }}
  <div class="layui-form-item">
    <label class="layui-form-label required">辅种的站点</label>
    <div class="layui-input-block" id="reseed_sites_view">
    </div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label required">辅种的下载器</label>
    <div class="layui-input-block" id="reseed_clients_view">
    </div>
    <div class="layui-form-mid layui-word-aux"><i class="layui-icon layui-icon-tips"></i> 如果您新增站点或者新增下载器，需要再次编辑计划任务并勾选。</div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label">自动校验</label>
    <div class="layui-input-block">
      <input type="checkbox" name="auto_check" lay-skin="switch" lay-text="YES|NO" lay-filter="auto_check" id="auto_check">
      <tip>辅种添加的任务，自动开始校验（如果您的QB下载器，添加的辅种任务不会自动开始校验，可以勾选此设置）。此功能在TR以及低版本QB中属于默认行为，是否勾选都不影响自动校验；</tip>
    </div>
  </div>
  {{# } }}

  {{# if (d.type === 'move') { }}
  <div class="layui-form-item">
    <label class="layui-form-label required">来源下载器</label>
    <div class="layui-input-block" id="form_clients_view">
    </div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label required">转移到下载器</label>
    <div class="layui-input-block" id="to_clients_view">
    </div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label required">过滤器</label>
    <div class="layui-input-block">
      <input type="hidden" name="path_filter" id="path_filter" lay-verify="path_filter" class="layui-input">
      <div id="path_filter_view"></div>
      <div class="layui-form-mid layui-word-aux"><i class="layui-icon layui-icon-tips"></i> 转移时排除的数据目录，不转移此路径内种子(为空时，不排除)。（此目录是客户端内做种的数据目录）</div>
    </div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label required">选择器</label>
    <div class="layui-input-block">
      <input type="hidden" name="path_selector" id="path_selector" lay-verify="path_selector" class="layui-input">
      <div id="path_selector_view"></div>
      <div class="layui-form-mid layui-word-aux"><i class="layui-icon layui-icon-tips"></i> 转移时允许的数据目录，只转移此路径内种子(为空时，全转移) 【优先级：过滤器 ＞ 选择器】。（此目录是客户端内做种的数据目录）</div>
    </div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label required">路径转换类型</label>
    <div class="layui-input-inline">
      <select name="path_type" lay-filter="path_type" id="path_type" lay-verify="required" lay-reqtext="路径转换类型不能为空">
        <option value="" selected="">请选择转换类型</option>
        <option value="0">相等</option><option value="1">减</option><option value="2">加</option><option value="3">替换</option>
      </select>
    </div>
    <div class="layui-form-mid layui-word-aux"><i class="layui-icon layui-icon-tips"></i> 用于相对路径与绝对路径之间互相转换，实现种子对应资源目录，是客户端之间转移做种的重要步骤。</div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label required">路径转换规则</label>
    <div class="layui-input-block">
      <textarea placeholder="请输入路径转换规则，每一行代表一条规则；" class="layui-textarea" name="path_rule"></textarea>
      <tip>路径转换规则为空时，在转移种子时默认会设置路径转换类型为相等；路径转换规则每一行代表一条规则，每条规则如果包含两个文件夹，请用<span class="layui-badge">{#**#}</span></b>作为分隔符（分隔符用来分隔 源路径和目标路径）。<br />举例：路径转换类型<span class="layui-badge layui-bg-cyan">加</span>，路径转换规则<span class="layui-badge layui-bg-black">/downloads{#**#}/volume1</span>，<span class="layui-badge layui-bg-blue">转移时从路径前段匹配/downloads成功时，加/volume1得到完整的转换后路径：/volume1/downloads</span>。<br />
        路径转换类型<span class="layui-badge layui-bg-cyan">替换</span>，路径转换规则<span class="layui-badge layui-bg-black">/downloads{#**#}/volume1/downloads</span>，<span class="layui-badge layui-bg-blue">转移时从路径前段匹配/downloads成功时，替换得到完整的转换后路径：/volume1/downloads</span>。</tip>
    </div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label">跳校验</label>
    <div class="layui-input-block">
      <input type="checkbox" name="skip_check" lay-skin="switch" lay-text="YES|NO" lay-filter="skip_check" id="skip_check">
      <tip>转移时，跳过校验（此功能需要下载器支持）。</tip>
    </div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label">暂停</label>
    <div class="layui-input-block">
      <input type="checkbox" name="paused" lay-skin="switch" lay-text="YES|NO" lay-filter="paused" id="paused">
      <tip>转移后，不要自动开始。</tip>
    </div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label">删除源做种</label>
    <div class="layui-input-block">
      <input type="checkbox" name="delete_torrent" lay-skin="switch" lay-text="YES|NO" lay-filter="delete_torrent" id="delete_torrent">
      <tip>转移成功，删除来源下载器内的种子。<span class="layui-badge">风险提示：第一次转移时请不要勾选，万一路径配置错误，将会删除客户端正常做种的种子。非必要，请勿勾选！！！</span></tip>
    </div>
  </div>
  {{# } }}

  {{# if (d.type === 'rss') { }}
  <div class="layui-form-item">
    <label class="layui-form-label required">Rss站点</label>
    <div class="layui-input-block">
      <div id="rss_sites_view"></div>
      <div class="layui-form-mid layui-word-aux"><i class="layui-icon layui-icon-tips"></i> 未配置的站点，将会显示为禁用状态。<a href="javascript:;" layuimini-href="page/setting/sites.html" target="_self" style="color:#1e9fff">站点设置</a></div>
    </div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label">RSS订阅地址</label>
    <div class="layui-input-block">
      <input type="text" name="urladdress" placeholder="请输入RSS订阅地址" class="layui-input" value="">
      <tip>未配置URL地址时，将会执行默认。</tip>
    </div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label required">下载器</label>
    <div class="layui-input-block" id="rss_clients_view">
    </div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label">下载模式</label>
    <div class="layui-input-block">
      <input type="checkbox" name="workingMode" lay-skin="switch" lay-text="Watch模式|Rpc模式" lay-filter="workingMode" id="workingMode">
      <tip>Rpc模式：可以远程访问下载器的API接口，POST种子元数据；Watch模式：仅往下载器设置的watch监控目录内写入种子文件。</tip>
    </div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label">数据目录</label>
    <div class="layui-input-block">
      <input type="text" name="downloadsDir" placeholder="请输入数据目录" class="layui-input">
      <tip><span class="layui-badge">优先级：中</span>下载器的数据目录。如果此处留空，将会使用过滤器设置的数据目录或者下载器设置的数据目录；如果都未设置，将会采用下载器默认值。</tip>
    </div>
  </div>

  <div class="layui-form-item">
    <label class="layui-form-label required">筛选规则</label>
    <div class="layui-input-block">
      <div id="rss_filter_view"></div>
      <div class="layui-form-mid layui-word-aux"><i class="layui-icon layui-icon-tips"></i> 满足所选的规则，Rss时才会下载。</div>
    </div>
  </div>
  {{# } }}

  {{# if (d.type === 'spiders') { }}
  <div class="layui-form-item">
    <label class="layui-form-label required">站点爬虫</label>
    <div class="layui-input-block">
      <div id="spiders_sites_view"></div>
      <div class="layui-form-mid layui-word-aux"><i class="layui-icon layui-icon-tips"></i> 未配置的站点，将会显示为禁用状态。<a href="javascript:;" layuimini-href="page/setting/sites.html" target="_self" style="color:#1e9fff">站点设置</a></div>
    </div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label">种子列表页地址</label>
    <div class="layui-input-block">
      <input type="text" name="urladdress" placeholder="请输入种子列表页地址" class="layui-input" value="">
      <tip>未配置URL地址时，将会执行默认。</tip>
    </div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label required">下载器</label>
    <div class="layui-input-block" id="spiders_clients_view">
    </div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label">下载模式</label>
    <div class="layui-input-block">
      <input type="checkbox" name="workingMode" lay-skin="switch" lay-text="Watch模式|Rpc模式" lay-filter="workingMode" id="workingMode">
      <tip>Rpc模式：可以远程访问下载器的API接口，POST种子元数据；Watch模式：仅往下载器设置的watch监控目录内写入种子文件。</tip>
    </div>
  </div>
  <div class="layui-form-item">
    <label class="layui-form-label">数据目录</label>
    <div class="layui-input-block">
      <input type="text" name="downloadsDir" placeholder="请输入数据目录" class="layui-input">
      <tip><span class="layui-badge">优先级：中</span>下载器的数据目录。如果此处留空，将会使用过滤器设置的数据目录或者下载器设置的数据目录；如果都未设置，将会采用下载器默认值。</tip>
    </div>
  </div>

  <div class="layui-form-item">
    <label class="layui-form-label required">筛选规则</label>
    <div class="layui-input-block">
      <div id="spiders_filter_view"></div>
      <div class="layui-form-mid layui-word-aux"><i class="layui-icon layui-icon-tips"></i> 满足所选的规则，爬虫才会向下载器推送下载任务。</div>
    </div>
  </div>
  {{# } }}

  {{# if (d.type === 'url') { }}
  <div class="layui-form-item">
    <label class="layui-form-label required">URL地址</label>
    <div class="layui-input-block">
      <input type="text" name="urladdress" lay-verify="required" placeholder="请输入URL地址" class="layui-input" value="http://">
    </div>
  </div>
  {{# } }}

  {{# if (d.type === 'shell') { }}
  <div class="layui-form-item">
    <label class="layui-form-label required">脚本内容</label>
    <div class="layui-input-block">
      <textarea placeholder="请输入脚本内容" class="layui-textarea" name="body"></textarea>
    </div>
  </div>
  {{# } }}
</script>

<!-- 模板：辅种任务 [站点] 复选框 -->
<script id="reseed_sites_tpl" type="text/html">
  {{#  layui.each(d, function(index, item){ }}
  <input type="checkbox" name="sites[{{item}}]" title="{{item}}" checked>
  {{#  }); }}
</script>

<!-- 模板：辅种任务 [下载器] 复选框 -->
<script id="reseed_clients_tpl" type="text/html">
  {{#  layui.each(d, function(index, item){ }}
  <input type="checkbox" name="clients[{{item.uuid}}]" title="{{ item.name }}" checked>
  {{#  }); }}
</script>

<!-- 模板：转移任务来源 [下载器] 单选框 -->
<script id="form_clients_tpl" type="text/html">
  {{#  layui.each(d, function(index, item){ }}
  <input type="radio" name="form_clients" value="{{item.uuid}}" title="{{ item.name }}">
  {{#  }); }}
</script>

<!-- 模板：转移任务目标 [下载器] 单选框 -->
<script id="to_clients_tpl" type="text/html">
  {{#  layui.each(d, function(index, item){ }}
  <input type="radio" name="to_clients" value="{{item.uuid}}" title="{{ item.name }}">
  {{#  }); }}
</script>

<!-- 模板：下载任务 [站点] 单选框 -->
<script id="rss_sites_tpl" type="text/html">
  {{#  layui.each(d, function(index, item){ }}
  <input type="radio" name="site" value="{{item.site}}" title="{{ item.site }}{{ item.nickname && item.site != item.nickname ? ' ' + item.nickname : '' }}" {{ item.disabled ? ' disabled' : '' }}>
  {{#  }); }}
</script>

<!-- 模板：下载任务 [下载器] 单选框 -->
<script id="rss_clients_tpl" type="text/html">
  {{#  layui.each(d, function(index, item){ }}
  <input type="radio" name="clients" value="{{item.uuid}}" title="{{ item.name }}">
  {{#  }); }}
</script>

<!-- 模板：下载任务 [筛选规则过滤器] 单选框 -->
<script id="rss_filter_tpl" type="text/html">
  {{#  layui.each(d, function(index, item){ }}
  <input type="radio" name="filter" value="{{item.uuid}}" title="{{ item.name }}">
  {{#  }); }}
</script>

<!-- 模板：计划任务 [执行周期] 组合 -->
<script type="text/html" id="crontab_where_tpl">
  {{# if (d.weeks) { }}
  <div class="layui-inline">
    <div class="layui-input-inline" style="width: 100px;">
      <select name="weeks" lay-filter="weeks" lay-verify="required" id="weeks">
        <option value="1" selected>周一</option>
        <option value="2">周二</option>
        <option value="3">周三</option>
        <option value="4">周四</option>
        <option value="5">周五</option>
        <option value="6">周六</option>
        <option value="0">周日</option>
      </select>
    </div>
  </div>
  {{# } }}
  {{# if (d.day) { }}
  <div class="layui-inline">
    <div class="layui-input-inline" style="width: 140px;">
      <input type="number" name="day" lay-verify="required" lay-reqtext="{{ d.where === 'day_n' ? '间隔天数' : '每月第几日' }}不能为空" placeholder="请输入{{ d.where === 'day_n' ? '间隔天数' : '每月第几日' }}" class="layui-input" id="day">
    </div>
    <div class="layui-form-mid">{{ d.where === 'day_n' ? '天' : '日' }}</div>
  </div>
  {{# } }}
  {{# if (d.hour) { }}
  <div class="layui-inline">
    <div class="layui-input-inline" style="width: 100px;">
      <input type="number" name="hour" lay-verify="required" lay-reqtext="小时不能为空" placeholder="请输入小时" class="layui-input" id="hour">
    </div>
    <div class="layui-form-mid">小时</div>
  </div>
  {{# } }}
  {{# if (d.minute) { }}
  <div class="layui-inline">
    <div class="layui-input-inline" style="width: 100px;">
      <input type="number" name="minute" lay-verify="required" lay-reqtext="分钟不能为空" placeholder="请输入分钟" class="layui-input" id="minute">
    </div>
    <div class="layui-form-mid">分钟</div>
  </div>
  {{# } }}
</script>

<!-- 模板：表格头工具栏 -->
<script type="text/html" id="tableTopToolbar">
  <div class="layui-btn-container">
    <button class="layui-btn layui-btn-danger layui-btn-sm" lay-event="clearReseedCache">清理辅种缓存</button>
    <button class="layui-btn layui-btn-danger layui-btn-sm" lay-event="clearMoveCache">清理转移缓存</button>
    <button class="layui-btn layui-btn-danger layui-btn-sm" lay-event="clearAllLogs" title="清理所有任务的日志">清理任务日志</button>
    <button class="layui-btn layui-btn-danger layui-btn-sm" lay-event="refreshCrontab" title="刷新所有任务，重新生成任务命令">刷新任务</button>
  </div>
</script>

<!-- 模板：表格行工具条 -->
<script type="text/html" id="tableToolbar">
  <span class="layui-badge layui-bg-cyan" lay-event="run">运行</span>
  <span class="layui-badge layui-bg-cyan" lay-event="stop">停止</span>
  <span class="layui-badge layui-bg-orange" lay-event="log">日志</span>
  <span class="layui-badge layui-bg-gray" lay-event="clearLog">清理</span>
  <span class="layui-badge layui-bg-green" lay-event="edit">编辑</span>
  <span class="layui-badge" lay-event="delete">删除</span>
</script>
<script>
  layui.use(['table','form','miniPage','laytpl','code','transfer','util'], function () {
    let $ = layui.$,
      layer = layui.layer,
      table = layui.table,
      form = layui.form,
      miniPage = layui.miniPage,
      laytpl = layui.laytpl,
      transfer = layui.transfer,
      util = layui.util;

    const API = {
      tableList: '/Api/Config?config_filename=crontab&action=list'
      ,create: '/Api/Config'
      ,delete: '/Api/Config?config_filename=crontab&action=del'
      ,taskRun: '/Task/start'
      ,taskStop: '/Task/stop'
      ,taskLogs: '/Task/logs'
      ,taskClearLogs: '/Task/clearLogs'
    };

    const path_filter = 'path_filter'
      ,path_selector = 'path_selector'
      ,_height = 250;
    load_notify_channels();
    /**
     * 任务类型 选择框
     * @param {string} type       任务类型
     * @param {string} action     动作(增、删、改、查)
     * @param {string} where      执行周期
     * @param {object} formData   编辑时表单数据
     */
    let crontab_sel_action = function(type = '', action = '', where = 'day', formData = null) {
      let rule = {
          type: type
          ,action: action
          ,where: where
        }
        ,getTpl = crontab_type_tpl.innerHTML
        ,view = getById('crontab_type_view');
      //初始清空
      view.innerHTML = '';
      if (type === '') {
        getById('switch').checked = false;
        getById('notify-enable').checked = false;
        form.render();
        return ;
      }
      //新增任务时，清空任务名称 选中任务使能
      if (action === '' || action === 'add') {
        getById('name').value = '';
        getById('switch').checked = true;
        getById('notify-enable').checked = true;
      }
      laytpl(getTpl).render(rule, function(html) {
        view.innerHTML = html;
      });
      form.render();
      //联动：更新通知渠道
      notify_sel_action(type, formData);
      //联动：任务周期
      crontab_where_sel_action(rule.where);
      //联动：辅种任务
      reseed_sel_action(type, formData);
      //联动：转移任务
      move_sel_action(type, formData);
      //联动：RSS下载任务
      rss_sel_action(type, formData);
      //联动：免费种爬虫下载任务
      spiders_sel_action(type, formData);
    };

    /**
     * load notify channels
     */
    function load_notify_channels(callback) {
      $.getJSON('/Api/Config?config_filename=notify&action=list', function (d) {
        if (d.ret !== 200) {
          return;
        }
        let notify_tpl = notify_option_tpl.innerHTML
                ,notify_view = getById('notify_channels');
        if (d.data.total <= 0) {
          layer.alert('您还没有配置通知渠道，将会为您跳转到通知渠道设置！', function(index){
            layer.close(index);
            window.location = '/index.html#/page/setting/notify.html';
          });
          return;
        }
        laytpl(notify_tpl).render(d.data.items, function(html) {
          notify_view.innerHTML = html;
        });
        //回调
        form.render('select');
        callback && callback()
      });
    }
    /**
     * notify
     * @param {string} type       任务类型
     * @param {object} formData   编辑时表单数据
     */
    function notify_sel_action(type = '', formData) {
      if (null !== formData) {
        format_input('notify', formData);
      }
    }

    /**
     * 任务周期选择框
     * @param {string} where     执行周期
     */
    let crontab_where_sel_action = function(where = '') {
      let rule = {
          where: where
          ,weeks: where === 'week'
          ,day: $.inArray(where, ['day_n', 'month']) >= 0
          ,hour: $.inArray(where, ['hour', 'minute_n']) < 0
          ,minute: !!where
        }
        ,getTpl = crontab_where_tpl.innerHTML
        ,view = getById('crontab_where_view');
      //初始清空
      view.innerHTML = '';
      if (where === '') {
        return ;
      }
      laytpl(getTpl).render(rule, function(html) {
        view.innerHTML = html;
      });
      form.render();
    };

    /**
     * 清空crontab文本框
     */
    let clear_crontab_input = function() {
      console.log('清空crontab文本框');
      getById('crontab').value = '';
    };

    /**
     * 任务选择框联动，辅种任务
     * @param {string} type       任务类型
     * @param {object} formData   编辑时表单数据
     */
    let reseed_sel_action = function(type = '', formData) {
      if (type !== 'reseed') {
        return;
      }
      let callback = null;
      if (formData !== null) {
        format_input('sites', formData);
        format_input('clients', formData);
        delete formData.sites;
        delete formData.clients;
        console.log(formData);
        //定义回调
        callback = [
          function(){
            //取消复选框
            $('#reseed_sites_view').find(':input').each(function () {
              $(this).attr('checked', false);
            });
            form.val("form", formData);
          },
          function(){
            //取消复选框
            $('#reseed_clients_view :input').removeAttr("checked");
            form.val("form", formData);
          }
        ];
      }
      //辅种站点
      $.getJSON('/Api/Config?config_filename=user_sites&action=list', function (d) {
        let getTpl = reseed_sites_tpl.innerHTML
          ,view = getById('reseed_sites_view');
        if (d.ret !== 200) {
          return;
        }
        if (d.data.total <= 0) {
          layer.alert('您还没有配置站点，将会为您跳转到站点设置！', function(index){
            layer.close(index);
            window.location = '/index.html#/page/setting/sites.html';
          });
          return;
        }
        let data = Object.keys(d.data.items).map(function (key){
          return d.data.items[key].name;
        });
        laytpl(getTpl).render(data, function(html) {
          view.innerHTML = html;
        });
        //回调
        callback !== null && typeof callback[0] === 'function' && callback[0]();
        form.render('checkbox');
      });
      //辅种下载器
      $.getJSON('/Api/Config?config_filename=clients&action=list', function (d) {
        let getTpl = reseed_clients_tpl.innerHTML
          ,view = getById('reseed_clients_view');
        if (d.ret !== 200) {
          return;
        }
        if (d.data.total <= 0) {
          layer.alert('您还没有配置下载器，将会为您跳转到下载器设置！', function(index){
            layer.close(index);
            window.location = '/index.html#/page/setting/clients.html';
          });
          return;
        }
        laytpl(getTpl).render(d.data.items, function(html) {
          view.innerHTML = html;
        });
        //回调
        callback !== null && typeof callback[1] === 'function' && callback[1]();
        form.render('checkbox');
      });
    };

    /**
     * 任务选择框联动，转移做种任务
     * @param {string} type       任务类型
     * @param {object} formData   编辑时表单数据
     */
    let move_sel_action = function(type = '', formData) {
      if (type !== 'move') {
        return;
      }
      let callback = null;
      if (formData !== null) {
        console.log(formData);
        //定义回调
        callback = function(){
          form.val("form", formData);
        };
      }
      //获取所有下载器
      $.getJSON('/Api/Config?config_filename=clients&action=list', function (d) {
        if (d.ret !== 200) {
          return;
        }
        let formTpl = form_clients_tpl.innerHTML
          ,toTpl = to_clients_tpl.innerHTML
          ,form_view = getById('form_clients_view')
          ,to_view = getById('to_clients_view');
        if (d.data.total <= 0) {
          layer.alert('您还没有配置下载器，将会为您跳转到下载器设置！', function(index){
            layer.close(index);
            window.location = '/index.html#/page/setting/clients.html';
          });
          return;
        }
        //来源下载器
        laytpl(formTpl).render(d.data.items, function(html) {
          form_view.innerHTML = html;
        });
        //转移到下载器
        laytpl(toTpl).render(d.data.items, function(html) {
          to_view.innerHTML = html;
        });
        //回调
        callback !== null && typeof callback === 'function' && callback();
        form.render('radio');
      });
      //获取目录
      $.getJSON('/Api/Config?config_filename=folder&action=list', function (d) {
        if (d.ret !== 200) {
          return;
        }
        if (d.data.total <= 0) {
          layer.alert('您还没有配置目录，将会为您跳转到目录设置！', function(index){
            layer.close(index);
            window.location = '/index.html#/page/setting/folder.html';
          });
        }
        console.log(d);
        //过滤器
        transfer.render({
          elem: '#' + path_filter + '_view'
          ,id: path_filter
          ,parseData: function(res){
            return {
              "value": res.uuid
              ,"title": res.name
              ,"disabled": res.disabled
              ,"checked": res.checked
              ,"dir":res.dir
            }
          }
          ,title: ['全部目录', '排除目录']
          ,data: d.data.items
          ,value: formData !== null && formData.path_filter ? formData.path_filter.split(",") : []
          ,height: _height
          ,text: {
            none: '无数据'
            ,searchNone: '无匹配数据'
          }
          ,onchange: function(obj, index){
            var arr = ['左边', '右边'];
            console.log('来自 <strong>'+ arr[index] + '</strong> 的数据：',JSON.stringify(obj));
          }
        });
        //选择器
        transfer.render({
          elem: '#' + path_selector + '_view'
          ,id: path_selector
          ,parseData: function(res){
            return {
              "value": res.uuid
              ,"title": res.name
              ,"disabled": res.disabled
              ,"checked": res.checked
              ,"dir":res.dir
            }
          }
          ,title: ['全部目录', '选择目录']
          ,data: d.data.items
          ,value: formData !== null && formData.path_selector ? formData.path_selector.split(",") : []
          ,height: _height
          ,text: {
            none: '无数据'
            ,searchNone: '无匹配数据'
          }
          ,onchange: function(obj, index){
            var arr = ['左边', '右边'];
            console.log('来自 <strong>'+ arr[index] + '</strong> 的数据：',JSON.stringify(obj));
          }
        });
      });
    };

    /**
     * 任务选择框联动，RSS下载任务
     * @param {string} type       任务类型
     * @param {object} formData   编辑时表单数据
     */
    let rss_sel_action = function(type = '', formData) {
      if (type !== 'rss') {
        return;
      }
      let callback = null;
      if (formData !== null) {
        console.log(formData);
        //定义回调
        callback = function(){
          form.val("form", formData);
        };
      }
      //RSS支持的所有站点
      $.getJSON('/Api/getAllRssClass', {filter: true}, function (d) {
        let getTpl = rss_sites_tpl.innerHTML
          ,view = getById('rss_sites_view');
        if (d.ret !== 200) {
          return;
        }
        if (d.data.total <= 0) {
          layer.alert('您还没有配置站点，将会为您跳转到站点设置！', function(index){
            layer.close(index);
            window.location = '/index.html#/page/setting/sites.html';
          });
          return;
        }
        laytpl(getTpl).render(d.data.items, function(html) {
          view.innerHTML = html;
        });
        //回调
        callback !== null && typeof callback === 'function' && callback();
        form.render('radio');
      });
      //RSS使用的下载器
      $.getJSON('/Api/Config?config_filename=clients&action=list', function (d) {
        let getTpl = rss_clients_tpl.innerHTML
          ,view = getById('rss_clients_view');
        if (d.ret !== 200) {
          return;
        }
        if (d.data.total <= 0) {
          layer.alert('您还没有配置下载器，将会为您跳转到下载器设置！', function(index){
            layer.close(index);
            window.location = '/index.html#/page/setting/clients.html';
          });
          return;
        }
        laytpl(getTpl).render(d.data.items, function(html) {
          view.innerHTML = html;
        });
        //回调
        callback !== null && typeof callback === 'function' && callback();
        form.render('radio');
      });
      //RSS使用的筛选规则过滤器
      $.getJSON('/Api/Config?config_filename=filter&action=list', function (d) {
        let getTpl = rss_filter_tpl.innerHTML
          ,view = getById('rss_filter_view');
        if (d.ret !== 200) {
          return;
        }
        if (d.data.total <= 0) {
          layer.alert('您还没有配置筛选规则过滤器，将会为您跳转到过滤器设置！', function(index){
            layer.close(index);
            window.location = '/index.html#/page/setting/filter.html';
          });
          return;
        }
        laytpl(getTpl).render(d.data.items, function(html) {
          view.innerHTML = html;
        });
        //回调
        callback !== null && typeof callback === 'function' && callback();
        form.render('radio');
      });
    };

    /**
     * 任务选择框联动，免费种爬虫下载任务
     * @param {string} type       任务类型
     * @param {object} formData   编辑时表单数据
     */
    let spiders_sel_action = function(type = '', formData) {
      if (type !== 'spiders') {
        return;
      }
      let callback = null;
      if (formData !== null) {
        console.log(formData);
        //定义回调
        callback = function(){
          form.val("form", formData);
        };
      }
      //支持的所有站点
      $.getJSON('/Api/getAllSpidersClass', {filter: true}, function (d) {
        let getTpl = rss_sites_tpl.innerHTML
            ,view = getById('spiders_sites_view');
        if (d.ret !== 200) {
            return;
        }
        if (d.data.total <= 0) {
          layer.alert('您还没有配置站点，将会为您跳转到站点设置！', function(index){
            layer.close(index);
            window.location = '/index.html#/page/setting/sites.html';
          });
          return;
        }
        laytpl(getTpl).render(d.data.items, function(html) {
          view.innerHTML = html;
        });
        //回调
        callback !== null && typeof callback === 'function' && callback();
        form.render('radio');
      });
      //使用的下载器
      $.getJSON('/Api/Config?config_filename=clients&action=list', function (d) {
        let getTpl = rss_clients_tpl.innerHTML
            ,view = getById('spiders_clients_view');
        if (d.ret !== 200) {
          return;
        }
        if (d.data.total <= 0) {
          layer.alert('您还没有配置下载器，将会为您跳转到下载器设置！', function(index){
            layer.close(index);
            window.location = '/index.html#/page/setting/clients.html';
          });
          return;
        }
        laytpl(getTpl).render(d.data.items, function(html) {
          view.innerHTML = html;
        });
        //回调
        callback !== null && typeof callback === 'function' && callback();
        form.render('radio');
      });
      //使用的筛选规则过滤器
      $.getJSON('/Api/Config?config_filename=filter&action=list', function (d) {
        let getTpl = rss_filter_tpl.innerHTML
            ,view = getById('spiders_filter_view');
        if (d.ret !== 200) {
            return;
        }
        if (d.data.total <= 0) {
          layer.alert('您还没有配置筛选规则过滤器，将会为您跳转到过滤器设置！', function(index){
              layer.close(index);
              window.location = '/index.html#/page/setting/filter.html';
          });
          return;
        }
        laytpl(getTpl).render(d.data.items, function(html) {
          view.innerHTML = html;
        });
        //回调
        callback !== null && typeof callback === 'function' && callback();
        form.render('radio');
      });
    };
    /**
     * 初始化表格
     */
    table.render({
      elem: '#tableId'
      ,url: API.tableList
      ,toolbar: '#tableTopToolbar'
      ,defaultToolbar: ['filter', 'print', {
        title: '提示'
        ,layEvent: 'LAYTABLE_TIPS'
        ,icon: 'layui-icon-tips'
      }]
      ,parseData: function(res){
        console.log(res);
        return {
          "code": res.ret === 200 ? 0 : res.ret,
          "msg": res.msg,
          "count": res.data.total,
          "data": res.data.items
        };
      }
      ,cols: [[
        {field: 'name', title: '任务名称', width:180, align: "center", sort: true, fixed: 'left'}
        ,{field: 'uuid', title: 'UUID', width:80, align: "center", hide: true}
        ,{field: 'type', title: '任务类型', width:150, align: "center", sort: true
          ,templet: function(d){
            let type = '';
            switch (d.type) {
              case 'reseed':
                type = '辅种任务';
                break;
              case 'move':
                type = '转移任务';
                break;
              case 'rss':
                type = 'Rss下载任务';
                break;
              case 'spiders':
                  type = '免费种爬虫下载任务';
                  break;
              case 'url':
                type = '访问URL';
                break;
              case 'shell':
                type = 'shell脚本';
                break;
              case 'patch':
                type = '备份目录';
                break;
              case 'ddns':
                type = '动态域名DDNS';
                break;
              case 'clear_log':
                type = '清除日志';
                break;
              default:
                break;
            }
            return type;
          }
        }
        ,{field: 'switch', title: '使能', width: 73, align: "center", sort: true
          ,templet: function(d){
            return d.switch ? '<span class="layui-badge layui-bg-green">YES</span>' : '<span class="layui-badge">NO</span>';
          }
        }
        ,{field: 'where', title: '执行周期', width:110, sort: true
          ,templet: function(d){
            return d.where ? '<span class="layui-badge layui-bg-orange">' + d.crontab + '</span>' : '';
          }
        }
        ,{field: 'urladdress', title: 'URL地址', width: 150, align: "center", sort: true
          ,templet: function(d){
            return d.urladdress || '';
          }
        }
        ,{field: 'body', title: '任务/脚本内容', minWidth: 180, sort: true
          ,templet: function(d){
            return d.body || d.command || '';
          }
        }
        ,{field: 'notify', title: '通知', minWidth: 73, sort: true
          ,templet: function(d){
            return (d.notify.enable ? '<span class="layui-badge layui-bg-green">' : '<span class="layui-badge">') + d.notify.channel + '</span>';
          }
        }
        ,{title: '操作', width: 270, templet: '#tableToolbar', fixed: "right", align: "center"}
      ]]
      ,done: function(res, curr, count){
        //如果是异步请求数据方式，res即为你接口返回的信息。
        //如果是直接赋值的方式，res即为：{data: [], count: 99} data为当前页数据、count为数据总长度
        console.log(res);
        //console.log(curr);  //得到当前页码
        //console.log(count); //得到数据总量
      }
      ,size: 'sm'
      ,page: false
      ,limit:500
    });

    /**
     * 监听：头工具栏事件
     */
    table.on('toolbar(tableFilter)', function(obj){
      let checkStatus = table.checkStatus(obj.config.id);
      let data = checkStatus.data;
      switch(obj.event){
        case 'clearReseedCache':
        case 'clearMoveCache':
          $.getJSON('/Task/clearCache', {'type': obj.event}, function (d) {
            if (d.ret === 200) {
              layer.msg(d.data.success ? '清理成功' : '清理失败');
              return;
            }
            layer.msg('接口请求失败：/Task/clearCache');
          });
        break;
        case 'refreshCrontab':
          $.getJSON('/Task/refresh', function (d) {
            if (d.ret === 200) {
              layer.msg(d.data.success ? '全部任务刷新成功' : '任务刷新失败');
              return;
            }
            layer.msg('接口请求失败：/Task/refresh');
          });
        break;
        case 'clearAllLogs':
          $.getJSON('/Task/clearAllLogs', function (d) {
            if (d.ret === 200) {
              layer.msg(d.data.success ? '清理任务日志'+ d.data.success + '个' : '任务日志清理失败');
              return;
            }
            layer.msg('接口请求失败：/Task/clearAllLogs');
          });
          break;
        case 'LAYTABLE_TIPS':
          layer.alert('这是工具栏右侧自定义的一个图标按钮');
        break;
      }
    });

    /**
     * 监听：行工具条
     */
    table.on('tool(tableFilter)', function(obj){
      let layEvent = obj.event;
      let tr = obj.tr;
      console.log('原始数据：', obj.data);
      switch (layEvent) {
        case 'run':
          $.ajax({
            url: API.taskRun,
            type:'get',
            data: {uuid: obj.data.uuid},
            success:function(data){
              if (data.ret !== 200) {
                layer.msg(data.msg);
                return;
              }
              let msg = data.data.success ? '运行成功' : '运行失败';
              layer.msg(msg, function () {
              });
            },
            complete: function () {
            }
          });
          break;
        case 'stop':
          $.ajax({
            url: API.taskStop,
            type:'get',
            data: {uuid: obj.data.uuid},
            success:function(data){
              if (data.ret !== 200) {
                layer.msg(data.msg);
                return;
              }
              let msg = data.data.success ? '已停止' : '操作失败';
              layer.msg(msg, function () {
              });
            },
            complete: function () {
            }
          });
          break;
        case 'clearLog':
          $.ajax({
            url: API.taskClearLogs,
            type:'get',
            data: {uuid: obj.data.uuid},
            success:function(data){
              if (data.ret !== 200) {
                layer.msg(data.msg);
                return;
              }
              let msg = data.data.success ? '日志清理成功' : '日志清理失败';
              layer.msg(msg, function () {
              });
            },
            complete: function () {
            }
          });
          break;
        case 'log':
          $.ajax({
            url: API.taskLogs,
            type:'get',
            data: {uuid: obj.data.uuid},
            success:function(data){
              if (data.ret !== 200) {
                layer.msg(data.msg);
                return;
              }
              let cronTimer;
              layer.open({
                type: 1
                ,title: false
                ,shadeClose: true
                ,area: ['1080px','700px']
                ,offset: '100px'
                ,shade: 0.8
                ,id: obj.data.uuid
                ,moveType: 1 //拖拽模式，0或者1
                ,content: '<pre class="layui-code" id="crontab_log">'+ data.data.logs +'</pre>'
                ,success: function(layero){
                  layui.code();
                  cronTimer = setInterval(function () {
                    $.ajax({
                      url: API.taskLogs,
                      type:'get',
                      data: {uuid: obj.data.uuid, last_line_number: 50},
                      success:function(data){
                        if (200 === data.ret) {
                          document.getElementById('crontab_log').innerHTML = data.data.logs;
                          layui.code();
                        } else {
                          layer.msg(data.msg);
                        }
                      }
                    });
                  }, 1000);
                }
                ,end: function () {
                  clearInterval(cronTimer);
                }
              });
            },
            complete: function () {
            }
          });
          break;
        case 'edit':
          getById('switch').checked = false;  //取消使能
          getById('notify-enable').checked = false;
          let formData = JSON.parse(JSON.stringify(obj.data));
          load_notify_channels(function () {
              crontab_sel_action(obj.data.type, 'edit', obj.data.where, formData);
              sessionStorage.setItem('edit', JSON.stringify(formData));
              form.val("form", formData);
              form.render();
          });
          break;
        case 'delete':
          layer.confirm('真的删除 '+obj.data.name +'吗？', function(index){
            $.ajax({
              url: API.delete,
              type:'get',
              data: {uuid: obj.data.uuid},
              success:function(data){
                if (data.ret !== 200) {
                  layer.msg(data.msg);
                  return;
                }
                layer.msg('删除成功', function () {
                });
                obj.del();
                layer.close(index);
              },
              complete: function () {
              }
            });
          });
          break;
        default:
          break;
      }
    });

    //监听行单击事件
    table.on('row(tableFilter)', function(obj){
      //同下
    });
    //监听行双击事件
    table.on('rowDouble(tableFilter)', function(obj){
      //console.log(obj.tr) //得到当前行元素对象
      console.log('原始数据：', obj.data) //得到当前行数据
      //obj.del(); //删除当前行
      //obj.update(fields) //修改当前行数据
    });

    /**
      * 初始化表单，要加上，不然刷新部分组件可能会不加载
      */
    form.render();

    //自定义验证规则
    form.verify({
      path_filter: function (value) {
        let elem = getById(path_filter)
          ,obj = transfer.getData(path_filter);
        elem.value = obj ? obj.map(v => {return v.value}).toString() : '';
      }
      ,path_selector: function (value) {
        let elem = getById(path_selector)
        ,obj = transfer.getData(path_selector);
        elem.value = obj ? obj.map(v => {return v.value}).toString() : '';
      }
    });
    //监听选择：类型
    form.on('select(type)', function(data){
      load_notify_channels(function () {
        crontab_sel_action(data.value, 'add');
      });
    });
    //监听选择：执行周期where
    form.on('select(where)', function(data){
      clear_crontab_input();
      crontab_where_sel_action(data.value);
    });
    //监听选择：执行周期weeks
    form.on('select(weeks)', function(data){
      clear_crontab_input();
    });
    //监听onchange变更事件
    util.event('id', {
      day: function(othis){
        clear_crontab_input();
      }
      ,hour: function(othis){
        clear_crontab_input();
      }
      ,minute: function(othis){
        clear_crontab_input();
      }
    },'change');

    //监听提交
    form.on('submit(saveBtn)', function (data) {
      $.ajax({
        url: API.create,
        type:'post',
        data: data.field,
        success:function(d){
          console.log(d);
          if (d.ret !== 200) {
            layer.msg(d.msg);
            return;
          }
          layer.msg('保存成功', function(){
            //miniPage.hashHome();
            window.location.reload();
          });
        },
        complete: function () {
        },
        error : function(request) {
          layer.alert('未知错误，请截图当前界面，然后求助于QQ群：859882209、931954050、924099912！', {icon: 2, title: '出错提示'});
        }
      });
      return false;
    });
  });
</script>
